package com.mobile.check.util;

import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import cn.droidlover.xdroidmvp.kit.Kits;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;

import com.mobile.check.beans.TaskInfo;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * 类名: DownloadManager
 * 作者: 李学伟
 * 日期: 2020年10月09日 09:20
 * 描述:
 */
public class DownloadManager {
    private static final String TAG = "DownloadManager";

    private static final AtomicReference<DownloadManager> INSTANCE = new AtomicReference<>();

    private HashMap<String, Call> downcalls;
    private OkHttpClient mClient;

    public static DownloadManager getInstance() {
        for (; ; ) {
            DownloadManager current = INSTANCE.get();
            if (current != null)
                return current;
            current = new DownloadManager();
            if (INSTANCE.compareAndSet(null, current))
                return current;
        }
    }

    private DownloadManager() {
        downcalls = new HashMap<>();
        mClient = new OkHttpClient.Builder().build();
    }

    /**
     * 取消下载任务
     *
     * @param url url
     */
    public void cancel(String url) {
        Call call = downcalls.get(url);
        if (call != null) {
            call.cancel();
        }
        downcalls.remove(url);
    }

    /**
     * 取消所有的下载任务
     */
    public void cancelAll() {
        for (String url : downcalls.keySet()) {
            cancel(url);
        }
    }

    /**
     * 下载文件
     *
     * @param task 下载任务
     */
    public Observable download(final TaskInfo task) {
        return Observable.create(new ObservableOnSubscribe<TaskInfo>() {
            @Override
            public void subscribe(ObservableEmitter<TaskInfo> e) throws Exception {
                if (task == null || task.getDownUrl() == null) {
                    e.onError(new Exception("错误的Url"));
                    return;
                }

                Request request = new Request.Builder()
                        .url(task.getDownUrl())
                        .build();
                Call call = mClient.newCall(request);
                downcalls.put(task.getDownUrl(), call);
                Kits.File.makeFolders(task.getTmpFilePath());
                File file = new File(task.getTmpFilePath());
                if (Kits.File.isFileExist(file.getPath())) {
                    Kits.File.deleteFile(file.getPath());
                }
                InputStream is = null;
                FileOutputStream fos = null;
                try {
                    Response response = call.execute();
                    long total = response.body().contentLength();
                    long sum = 0;
                    is = response.body().byteStream();
                    fos = new FileOutputStream(file, false);
                    byte[] buffer = new byte[2048 * 10];
                    int len;
                    while ((len = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, len);
                        sum += len;
                        Log.i(TAG, "已下载:" + sum + "/" + total);
                    }
                    task.setTaskFilePath(file.getPath());
                    e.onNext(task);
                    fos.flush();
                    downcalls.remove(file.getPath());
                    e.onComplete();
                } catch (IOException e1) {
                    e1.printStackTrace();
                    e.onError(e1);
                } finally {
                    if (null != is) {
                        is.close();
                    }
                    if (null != fos) {
                        fos.close();
                    }
                }
            }
        });
    }


    private Observable<DownloadInfo> getDownObservable(final DownloadInfo downloadInfo) {
        return Observable.create(new ObservableOnSubscribe<DownloadInfo>() {
            @Override
            public void subscribe(ObservableEmitter<DownloadInfo> e) throws Exception {
                String downUrl = downloadInfo.getDownUrl();
                Request request = new Request.Builder()
                        .url(downUrl)
                        .build();
                Call call = mClient.newCall(request);
                downcalls.put(downUrl, call);
                Kits.File.makeFolders(downloadInfo.getSaveFilePath());
                File file = new File(downloadInfo.getSaveFilePath());
                if (Kits.File.isFileExist(file.getPath())) {
                    Kits.File.deleteFile(file.getPath());
                }
                InputStream is = null;
                FileOutputStream fos = null;
                try {
                    Response response = call.execute();
                    long total = response.body().contentLength();
                    long sum = 0;
                    is = response.body().byteStream();
                    fos = new FileOutputStream(file, false);
                    byte[] buffer = new byte[2048 * 10];
                    int len;
                    while ((len = is.read(buffer)) != -1) {
                        fos.write(buffer, 0, len);
                        sum += len;
                        Log.i(TAG, "已下载:" + sum + "/" + total);
                    }
                    e.onNext(downloadInfo);
                    fos.flush();
                    downcalls.remove(file.getPath());
                    e.onComplete();
                } catch (IOException e1) {
                    e1.printStackTrace();
                    e.onError(e1);
                } finally {
                    if (null != is) {
                        is.close();
                    }
                    if (null != fos) {
                        fos.close();
                    }
                }
            }
        });


    }


    /**
     * 下载文件
     *
     * @param directory 目录
     */
    public Observable download(final TaskInfo taskInfo, String directory, String picDir) {
        List<DownloadInfo> list = createDownloadTask(taskInfo, directory, picDir);
        Observable<DownloadInfo>[] downList = new Observable[list.size()];
        for (DownloadInfo info : list) {
            downList[list.indexOf(info)] = getDownObservable(info);
        }
        return Observable.mergeArray(downList).map(new Function<DownloadInfo, TaskInfo>() {
            @Override
            public TaskInfo apply(DownloadInfo downloadInfo) throws Exception {
                if (downloadInfo.downUrl.endsWith(".zip")) {
                    File dir = new File(downloadInfo.getSaveFilePath());
                    ZipUtils.UnZipFolder(downloadInfo.getSaveFilePath(),dir.getPath());
                    Kits.File.deleteFile(downloadInfo.getSaveFilePath());
                    return new TaskInfo();
                }else{
                    TaskInfo newTaskInfo = new TaskInfo();
                    newTaskInfo.setTask_name(downloadInfo.getSaveName());
                    newTaskInfo.setId(taskInfo.getId());
                    newTaskInfo.setTaskFilePath(downloadInfo.getSaveFilePath());
                    newTaskInfo.setLocalFile(false);
                    newTaskInfo.setHadDowned(true);
                    return newTaskInfo;
                }

            }
        });
    }


    /**
     * 根据url获取构建DownloadInfo
     *
     * @param directory 目录
     * @return DownloadTask
     */
    private TaskInfo createDownloadTask(TaskInfo taskInfo, String directory) {
        String url = "";
        List<String> excelList = null;
        if (!taskInfo.isRepeatTask()) {
            excelList = taskInfo.getCheck_excel();
        } else {
            excelList = taskInfo.getRecheck_excel();
        }
        if (null != excelList && excelList.size() > 0) {
            url = excelList.get(0);
        }

        int lastIndex = url.contains("?") ? url.indexOf("?") : url.length();
        String filename = url.substring(url.lastIndexOf("/"), lastIndex);
        if (filename.contains("\\")) {
            filename = url.substring(url.lastIndexOf("\\") + 1, lastIndex);
        }
        int dianIndex = filename.lastIndexOf(".");
        String houzhui = filename.substring(dianIndex, filename.length());
        long currentTime = Calendar.getInstance().getTimeInMillis();
        filename = taskInfo.getTask_name() + currentTime + houzhui;
        taskInfo.setTmpFilePath(directory + File.separator + filename);
        taskInfo.setDownUrl(url);
        taskInfo.setLocalFile(false);
        taskInfo.setTaskFilePath(directory + File.separator + filename);
        return taskInfo;
    }

    private List<DownloadInfo> createDownloadTask(TaskInfo taskInfo, String directory, String picDir) {

        List<String> excelList = null;
        List<DownloadInfo> waitDownList = new ArrayList<>();


        if (!taskInfo.isRepeatTask()) {
            excelList = taskInfo.getCheck_excel();
        } else {
            excelList = taskInfo.getRecheck_excel();
        }
        if (null != excelList && excelList.size() > 0) {
            if (excelList.size() == 1) {
                String fileName = taskInfo.getTask_name();
                String filePath = getDownFilePathByUrl(fileName, directory, excelList.get(0));
                DownloadInfo info = new DownloadInfo(filePath, excelList.get(0), fileName);
                waitDownList.add(info);
            } else {
                for (int i = 0; i < excelList.size(); i++) {
                    String fileName = taskInfo.getTask_name();
                    String filePath = getDownFilePathByUrl(fileName, directory, excelList.get(i));
                    fileName = fileName + "_" + (i + 1);
                    DownloadInfo info = new DownloadInfo(filePath , excelList.get(i),fileName);
                    waitDownList.add(info);
                }
            }

        }
        String imgUrl = taskInfo.getInput_img();
        String filePath = getDownFilePathByUrl(taskInfo.getTask_name(), picDir, imgUrl);
        DownloadInfo info = new DownloadInfo(filePath, imgUrl);
        waitDownList.add(info);
        return waitDownList;
    }


    private String getDownFilePathByUrl(String fileName, String dir, String downUrl) {
        int lastIndex = downUrl.contains("?") ? downUrl.indexOf("?") : downUrl.length();
        String filename = downUrl.substring(downUrl.lastIndexOf("/"), lastIndex);
        if (filename.contains("\\")) {
            filename = downUrl.substring(downUrl.lastIndexOf("\\") + 1, lastIndex);
        }
        int dianIndex = filename.lastIndexOf(".");
        String houzhui = filename.substring(dianIndex, filename.length());
        filename = fileName  + houzhui;
        return dir + File.separator + filename;
    }


    class DownloadInfo {
        private String saveFilePath;
        private String downUrl;
        private String saveName;

        public DownloadInfo(String saveFilePath, String downUrl, String saveName) {
            this.saveFilePath = saveFilePath;
            this.downUrl = downUrl;
            this.saveName = saveName;
        }

        public DownloadInfo(String saveFilePath, String downUrl) {
            this.saveFilePath = saveFilePath;
            this.downUrl = downUrl;
        }

        public String getSaveFilePath() {
            return saveFilePath;
        }

        public void setSaveFilePath(String saveFilePath) {
            this.saveFilePath = saveFilePath;
        }

        public String getDownUrl() {
            return downUrl;
        }

        public void setDownUrl(String downUrl) {
            this.downUrl = downUrl;
        }

        public String getSaveName() {
            return saveName;
        }

        public void setSaveName(String saveName) {
            this.saveName = saveName;
        }
    }

}